// service/ai_ser/chatGPT.go
package ai_ser

import (
	"bufio"
	"encoding/json"
	"errors"
	"muziai-server/global"
	"muziai-server/models"

	"fmt"
	"github.com/sirupsen/logrus"
	"net/http"
	"strings"
)

type ChatGPTMessage struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}
type ChatGPTRequest struct {
	Model    string           `json:"model"`
	Messages []ChatGPTMessage `json:"messages"`
	Stream   bool             `json:"stream"`
}
type ChatGPTMsgBody struct {
	Id      string `json:"id"`
	Object  string `json:"object"`
	Created int    `json:"created"`
	Model   string `json:"model"`
	Choices []struct {
		Index int `json:"index"`
		Delta struct {
			Content string `json:"content"`
		} `json:"delta"`
		Logprobs     interface{} `json:"logprobs"`
		FinishReason interface{} `json:"finish_reason"`
	} `json:"choices"`
	SystemFingerprint interface{} `json:"system_fingerprint"`
}

type ChatGPT struct {
}

func (c ChatGPT) Send(req Request) (msgChan chan string, err error) {
	msgChan = make(chan string, 0)

	url := global.Config.AI.ProxyUrl
	fmt.Println(url)
	method := "POST"
	r := ChatGPTRequest{
		Model:    "gpt-3.5-turbo",
		Messages: []ChatGPTMessage{},
		Stream:   true,
	}
	// 获取提示词
	var role models.AiRoleModel
	err = global.DB.Take(&role, req.RoleID).Error
	if err != nil {
		err = errors.New("角色不存在")
		return
	}

	r.Messages = append(r.Messages, ChatGPTMessage{
		Role:    "system",
		Content: role.Prompt,
	})
	// 历史对话，查看之前会话的对话内容封装进去
	var chatList []models.ChatModel
	global.DB.Order("created_at").Find(&chatList, "session_id = ?", req.SessionID)
	for _, i2 := range chatList {
		r.Messages = append(r.Messages, ChatGPTMessage{
			Role:    "user",
			Content: i2.UserContent,
		})
		r.Messages = append(r.Messages, ChatGPTMessage{
			Role:    "assistant",
			Content: i2.AiContent,
		})
	}
	//当前提问的人说的话
	chatMsg := ChatGPTMessage{
		Role:    "user",
		Content: req.Content,
	}

	// 读取对话关联的图片
	var imageList []models.ChatToImageModel
	global.DB.Find(&imageList, "chat_id = ?", req.ChatID)
	if len(imageList) > 0 {
		var outAll string
		for _, model := range imageList {
			outAll += fmt.Sprintf("${{{%s}}}\n", model.ImageOcrContent)
		}
		chatMsg.Content += outAll

		// 如果本轮传了图片，我才加上system
		r.Messages[0].Content += "\n从现在开始，我赋予你一项能力，如果在后续的提问过程中，如果用户以${{{}}}格式向你提问，你需要先按照固定格式输出，根据AI识别，图片中的内容是，然后把格式中的内容进行输出，然后需要按照用户的提问进行回答"
	}

	//如果有图片，将图片的对话也加入进去
	r.Messages = append(r.Messages, chatMsg)

	byteData, _ := json.Marshal(r)
	fmt.Println(string(byteData))
	client := &http.Client{}
	rr, err := http.NewRequest(method, url, strings.NewReader(string(byteData)))

	if err != nil {
		logrus.Error(err)
		return
	}
	rr.Header.Add("Authorization", fmt.Sprintf("Bearer %s", global.Config.AI.ApiKey))
	rr.Header.Add("User-Agent", "Apifox/1.0.0 (https://apifox.com)")
	rr.Header.Add("Content-Type", "application/json")

	res, err := client.Do(rr)
	if err != nil {
		logrus.Error(err)
		return
	}
	go func() {
		defer res.Body.Close()
		scanner := bufio.NewScanner(res.Body)
		scanner.Split(bufio.ScanLines) // 按照行读

		for scanner.Scan() {
			msg := scanner.Text()
			if msg == "" {
				continue
			}
			if msg == "data: [DONE]" {
				// 读完了
				break
			}
			var m ChatGPTMsgBody
			err = json.Unmarshal([]byte(msg[5:]), &m)
			if err != nil {
				fmt.Println(msg, err)
				continue
			}
			// 检查是否是结束消息
			if len(m.Choices) > 0 && m.Choices[0].FinishReason == "stop" {
				break
			}
			msgChan <- m.Choices[0].Delta.Content

		}
		close(msgChan)
	}()
	return
}
